package com.flyan.game.motafx.core.event.listener;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.time.TimerAction;
import com.flyan.game.motafx.core.event.Event;
import com.flyan.game.motafx.core.map.FloorMap;
import com.flyan.game.motafx.core.util.core.GameUtils;
import javafx.util.Duration;
import lombok.Getter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 事件监听器
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/2/11
 */
public abstract class EventListener {

    /***
     * 事件所在楼层编号
     */
    @Getter
    protected final Integer floorNumber;

    public EventListener(Integer floorNumber) {
        this.floorNumber = floorNumber;
    }

    /**
     * @return 监听器类型
     */
    public abstract String type();

    /**
     * @return 是否触发
     */
    public abstract boolean isOccur();

    /**
     * @return 是否可重复触发
     */
    public boolean isRepeated() {
        return false;
    }

    /**
     * 事件列表，按顺序发生
     */
    private final List<Event> events = new ArrayList<>();

    public void addEvent(Event event) {
        events.add(event);
    }

    /**
     * 事件发生
     *
     * @return 是否发生成功
     */
    public boolean occur() {
        /* 事件发生楼层是否一致 */
        FloorMap currentFloor = GameUtils.app().towerMap.getCurrentFloor();
        if (!floorNumber.equals(currentFloor.getFloorInfo().getNumber())) {
            return false;
        }

        if (!isOccur()) {
            return false;
        }

        /* 按顺序发生事件 */
        Iterator<Event> eventIt = events.iterator();
        AtomicReference<TimerAction> timerRef = new AtomicReference<>(null);
        final Duration durationUnit = Duration.millis(10); // 持续时间最小单位
        AtomicReference<Duration> duration = new AtomicReference<>(new Duration(0));
        AtomicReference<Duration> currentEventDuration = new AtomicReference<>(new Duration(0));
        var timer = FXGL.run(() -> {
            if (eventIt.hasNext()) {
                if (currentEventDuration.get().lessThanOrEqualTo(duration.get())) { // 当前发生事件还未完成
                    Event e = eventIt.next();
                    e.occur();
                    if (e.duration() != Duration.ZERO) {
                        /* 记录当前发生事件持续时间到哪 */
                        currentEventDuration.set(currentEventDuration.get().add(e.duration()));
                    }
                }
            } else {
                if (timerRef.get() != null) {
                    timerRef.get().expire();
                }
            }
            duration.set(duration.get().add(durationUnit));
        }, durationUnit);
        timerRef.set(timer);
        return true;
    }

}
